package models

import (
	"errors"
	"strconv"

	"github.com/jinzhu/gorm"
)

// ComponentOrder 采购订单表
type ComponentOrder struct {
	gorm.Model
	Operator string `gorm:"size:255"`
	Remarks  string
	Amount   float32
	Freight  float32
	State    string `gorm:"default:'未完成'"`
}

// ComponentGoods 采购订单详细产品表
type ComponentGoods struct {
	ComponentOrderID uint
	GoodsID          string
	Number           uint
	Unit             string
}

// CreateComponentOrder 创建采购订单
func CreateComponentOrder(order *ComponentOrder, goods []ComponentGoods) (*ComponentOrderInfo, error) {
	tx := db.Begin()

	err := tx.Table("component_orders").Create(order).Error
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	for _, v := range goods {
		v.ComponentOrderID = order.ID
		err = tx.Table("component_goods").Create(&v).Error
		if err != nil {
			tx.Rollback()
			return nil, err
		}
	}

	orderInfo, err := getComponentOrder(tx, strconv.Itoa(int(order.ID)))
	if err != nil {
		tx.Rollback()
		return nil, err
	}
	tx.Commit()
	return orderInfo, nil
}

// DeleteComponentOrder 删除采购订单
func DeleteComponentOrder(orderID string) error {
	ok, err := componentOrderConfirmed(orderID)
	if err != nil {
		return err
	}
	if ok {
		return errors.New("无法删除已经确认订单")
	}

	tx := db.Begin()

	err = tx.Table("component_goods").Where(
		"component_order_id = ?", orderID).Delete(ComponentGoods{}).Error
	if err != nil {
		tx.Rollback()
		return err
	}

	err = tx.Table("component_orders").Unscoped().Where(
		"id = ?", orderID).Delete(ComponentOrder{}).Error
	if err != nil {
		tx.Rollback()
		return err
	}

	tx.Commit()
	return nil
}

// ConfirmComponentOrder 确认订单
func ConfirmComponentOrder(orderID string, freight float32) (*ComponentOrderInfo, error) {
	ok, err := componentOrderConfirmed(orderID)
	if err != nil {
		return nil, err
	}
	if ok {
		return nil, errors.New("订单请勿重复确认")
	}

	tx := db.Begin()

	err = tx.Table("component_orders").Where("id = ?", orderID).UpdateColumns(ComponentOrder{
		State:   "已完成",
		Freight: freight}).Error
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	var goods []ComponentGoods
	err = tx.Table("component_goods").Where("component_order_id = ?", orderID).Find(&goods).Error
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	for _, v := range goods {
		number, err := getComponentNumber(tx, v.GoodsID)
		if err != nil {
			tx.Rollback()
			return nil, err
		}
		var updateNum uint = 0
		if v.Unit == "箱" {
			component := GetComponent(v.GoodsID)
			if err != nil {
				tx.Rollback()
				return nil, err
			}
			if component.PackgeNum != 0 && v.Number != 0 {
				updateNum = number + component.PackgeNum*v.Number
			}
		} else {
			updateNum = number + v.Number
		}
		err = updateComponentNumber(tx, v.GoodsID, updateNum) // DONE 确认购买订单量，先查出配件的库存，然后加上新买的量。
		if err != nil {
			tx.Rollback()
			return nil, err
		}
	}

	orderInfo, err := getComponentOrder(tx, orderID)
	if err != nil {
		tx.Rollback()
		return nil, err
	}
	tx.Commit()
	return orderInfo, nil
}

// ComponentOrderInfo 订单信息
type ComponentOrderInfo struct {
	ComponentOrder
	Goods []Component
}

// ListComponentOrders 所有订单
func ListComponentOrders() (orders []ComponentOrderInfo, err error) {
	err = db.Table("component_orders").Select(
		"id, created_at, operator, amount, remarks, state, freight").Find(&orders).Error
	if err != nil {
		return
	}

	for index, v := range orders {
		err = db.Raw(`select t2.id,t2.no, t2.name, t2.supply,t2.purchase_price, t1.number, t1.unit,t2.merchandise_safety_stock,t2.number stock_number from component_goods as t1 left outer join 
				components as t2 on t1.goods_id = t2.id where t1.component_order_id = ?`, v.ID).Scan(&orders[index].Goods).Error
		if err != nil {
			return
		}
	}
	return
}

// GetComponentOrder 获取订单信息
func getComponentOrder(tx *gorm.DB, orderID string) (*ComponentOrderInfo, error) {
	var order ComponentOrderInfo
	err := tx.Table("component_orders").Select(
		"id, created_at, operator, amount, remarks, state, freight").Where("id = ?", orderID).First(&order).Error
	if err != nil {
		return nil, err
	}

	err = tx.Raw(`select t2.id, t2.no, t2.name, t2.supply,t2.purchase_price, t1.number, t1.unit,t2.merchandise_safety_stock,t2.number stock_number from component_goods as t1 left outer join
			components as t2 on t1.goods_id = t2.id where t1.component_order_id = ?`, orderID).Scan(&order.Goods).Error
	if err != nil {
		return nil, err
	}
	return &order, nil
}

func componentOrderConfirmed(orderID string) (bool, error) {
	info := struct {
		State string `json:"state"`
	}{}
	err := db.Table("component_orders").Select("state").Where("id = ?", orderID).First(&info).Error
	if err != nil {
		return false, err
	}

	if info.State == "已完成" {
		return true, nil
	}

	return false, nil
}
